/* **********************************************************************
版本: 2021.3.15f1c1
作者: wzz
日期: 2023-6-14
描述: 将log写入文本，方便查看！
***********************************************************************/

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using UnityEngine;

public class LogSave : MonoBehaviour
{
    private struct LogInfo
    {
        public string message;
        public LogType logType;
    }

    private static string filePath = "";
    private const string nowStr = "yyyy-MM-dd HH:mm:ss:ffff";
    private Thread thread;
    private static Queue<LogInfo> logInfos = new Queue<LogInfo>();
    private static readonly object m_lockObject = new object();
    private static readonly object m_lockObject2 = new object();
    private const int saveFileNume = 10;
    private StreamWriter writer;
    private StringBuilder stringBuilder;

    /// <summary>
    /// 打开保存
    /// </summary>
    public bool openSave = true;

    private void Awake()
    {
#if UNITY_EDITOR
#else
        openSave = false;
#endif

        if (!openSave)
            return;

        stringBuilder = new StringBuilder();

        thread = new Thread(OnUpdateThread);
        thread.Start();

        createFille();
        Application.logMessageReceived += LogMessageReceived;

        DontDestroyOnLoad(this.gameObject);
    }

    private void createFille()
    {
        string fileName = "UnityLog";
        string dirPath = string.Empty;

#if UNITY_EDITOR
        fileName += DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss");
        dirPath = Application.dataPath.Replace("Assets", "/Logs/");

#else
        dirPath = Application.persistentDataPath + "/Logs/";
#endif

        filePath = dirPath + fileName + ".txt";
        if (!Directory.Exists(dirPath))
            Directory.CreateDirectory(dirPath);

        CheckLogFiles();

        if (File.Exists(filePath))
        {
            File.WriteAllText(filePath, "");
        }
        else
        {
            using (File.Create(filePath)) { }
            ;
        }
        writer = new StreamWriter(filePath, true);
        writer.AutoFlush = true;
    }

    private void OnUpdateThread()
    {
        while (true)
        {
            lock (m_lockObject)
            {
                if (logInfos.Count > 0)
                {
                    LogInfo li = logInfos.Dequeue();

                    OnWriteFile(li.message);
                }
                else
                {
                    Thread.Sleep(10);
                }
            }
        }
    }

    /// <summary>
    /// 将消息写入文件
    /// </summary>
    public void OnWriteFile(string message)
    {
        try
        {
            writer.Write(message);
        }
        catch (Exception e)
        {
            Debug.Log($"write game log error, path={filePath} errorMessage={e.Message}");
        }
    }

    /// <summary>
    /// 接收消息
    /// </summary>
    private void LogMessageReceived(string message, string stackTrace, LogType type)
    {
        stringBuilder.Clear();
        stringBuilder.AppendLine(message);
        FilterStackTrace(stringBuilder, stackTrace);
        stringBuilder.AppendLine();
        AddMessage(stringBuilder.ToString(), type);
    }

    /// <summary>
    /// 过虑一些堆栈里的无用的信息
    /// </summary>
    private void FilterStackTrace(StringBuilder stringBuilder, string stackTrace)
    {
        var lines = stackTrace.Split("\n", StringSplitOptions.RemoveEmptyEntries);
        var str = "LogPro.";
        for (int i = 0; i < lines.Length; i++)
        {
            if (!lines[i].StartsWith(str))
                stringBuilder.AppendLine(lines[i]);
        }
    }

    /// <summary>
    /// 将消息添加进队列
    /// </summary>
    private void AddMessage(string message, LogType type)
    {
        lock (m_lockObject2)
        {
            LogInfo info = new LogInfo() { logType = type, message = message };
            string str = System.DateTime.Now.ToString(nowStr);
            info.message = str + "\n" + info.message;
            logInfos.Enqueue(info);
        }
    }

    /// <summary>
    /// 只保存前10个文件
    /// </summary>
    private void CheckLogFiles()
    {
        string dir = Path.GetDirectoryName(filePath);
        List<string> fileNames = new List<string>();
        foreach (var file in Directory.GetFiles(dir, "UnityLog*.txt"))
        {
            fileNames.Add(Path.GetFileNameWithoutExtension(file));
        }
        fileNames.Sort();

        for (int i = fileNames.Count - saveFileNume; i > 0; i--)
        {
            File.Delete(Path.Combine(dir, fileNames[i] + ".txt"));
        }
    }

    private void OnDestroy()
    {
        if (!openSave)
            return;
        try
        {
            Application.logMessageReceived -= LogMessageReceived;
            thread.Abort();
            writer.Dispose();
        }
        catch (Exception)
        {

            throw;
        }

    }
}